package com.bidevalution.business.impl;

import com.bidevalution.business.service.BeSectionHiddenService;
import com.bidevalution.business.service.BeSectionReportService;
import com.bidevalution.dao.entity.BeSectionParameter;
import com.bidevalution.dao.entity.BeSectionParameterKey;
import com.bidevalution.dao.mapper.BeSectionParameterMapper;
import com.bidevalution.support.context.Constants;
import com.qtp.core.common.HttpTookit;
import com.qtp.core.config.PropertiesTookit;
import com.qtp.core.model.RemoteResponse;
import com.qtp.core.model.Response;
import com.qtp.core.util.DesUtil;
import com.qtp.core.util.GsonUtil;
import com.qtp.core.util.OConvertUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huyiqi
 * @date 2020/4/15
 */
@Service(value = "beSectionHiddenService")
public class BeSectionHiddenServiceImpl implements BeSectionHiddenService {


    private static final Logger log = LoggerFactory.getLogger(BeSectionHiddenServiceImpl.class);

    private static final String PARAM_HIDDEN_PRINTED = "hiddenPrinted";
    private static final String DES_KEY = "PRINT_PDF_CHECK_TOKEN_KEY";
    /**
     * 暗标关联表报表模板路径
     */
    private static final String HIDDEN_REPORT_PATH = OConvertUtils.getString(PropertiesTookit.getValue("HIDDEN_REPORT_PATH"),"file:abglb.ureport.xml");
    /**
     * 打印token过期时间，默认1分钟
     */
    private static final Long PRINT_PDF_TOKEN_EXPIRS = OConvertUtils.getLong(PropertiesTookit.getValue("PRINT_PDF_TOKEN_EXPIRS"), (long) 60 * 1000);
    /**
     * 允许打印的次数，默认5次
     */
    private static final int PRINT_LIMIT_NUM = OConvertUtils.getInt(PropertiesTookit.getValue("PRINT_LIMIT_NUM"), 5);

    @Override
    public Response printPdfCheck(String sectionId, String userLoginName, String password) throws Exception {
        //验证密码
        if(showHiddenNum(userLoginName, password)) {
            //判断是否已经打印过（只能打印一次）
            if(isPrinted(sectionId)) {
                return Response.fail("已经打印过，不能再次打印");
            }
            return Response.ok(getToken());
        } else {
            return Response.fail("密码错误");
        }
    }

    @Override
    public void printHidden(String sectionId, String token, OutputStream os) throws Exception {
        if(checkToken(token) && !isPrinted(sectionId)) {
            log.info("==========printPdf==========token校验成功");
            log.info("==========printPdf==========token校验成功");
            //输出报表
            Map<String, Object> map = new HashMap<>(4);
            map.put("sectionId", sectionId);
            map.put("reportPaths", HIDDEN_REPORT_PATH);
            beSectionReportService.printPdf(map, os);
            //记录已经打印过
            addPrintNum(sectionId);
        } else {
            log.info("==========printPdf==========token校验失败");
        }
    }

    @Override
    public Response getButtonStatus(String sectionId) {
        if(isPrinted(sectionId)) {
            return Response.ok(Constants.STR_NO);
        } else {
            return Response.ok(Constants.STR_YES);
        }
    }


    private boolean showHiddenNum(String userLoginName,String password) {
        if(StringUtils.isBlank(password)||StringUtils.isBlank(userLoginName)) {
            return false;
        }
        Map<String, Object> params = new HashMap<>(8);
        params.put("loginType", 1);
        params.put("userName", userLoginName);
        params.put("userPassword", password);
        try {
            log.info("打印暗标关联表，验证密码：userLoginName="+userLoginName+"，password="+password);
            RemoteResponse result = HttpTookit.doPost(authLoginUrl + "/login/login.do", params);
            log.info("打印暗标关联表，验证密码返回结果："+ GsonUtil.toJson(result));
            String content = result.getContent();
            Response rsp = GsonUtil.parseJsonWithGson(content, Response.class);
            return rsp.isSuccess();
        } catch (Exception e) {
            log.error("验证密码失败", e);
        }
        return false;
    }

    private String getToken() throws Exception {
        String time = Long.toString(System.currentTimeMillis());
        return DesUtil.encrypt(time, DES_KEY);
    }

    private static boolean checkToken(String token) throws Exception {
        long oleTime = OConvertUtils.getLong(DesUtil.decrypt(token, DES_KEY));
        long now = System.currentTimeMillis();
        log.info("==========printPdf==========解密后的token："+oleTime);
        log.info("==========printPdf==========当前时间时间戳："+now);
        return System.currentTimeMillis() <= oleTime + PRINT_PDF_TOKEN_EXPIRS;
    }

    private boolean isPrinted(String sectionId) {
        int printedNum = 0;
        BeSectionParameter param = getPrintParam(sectionId);
        if(param!=null) {
            printedNum = OConvertUtils.getInt(param.getParamValue());
        }
        return printedNum >= PRINT_LIMIT_NUM;
    }

    private BeSectionParameter getPrintParam(String sectionId) {
        BeSectionParameterKey key = new BeSectionParameterKey();
        key.setParamId(PARAM_HIDDEN_PRINTED);
        key.setSectionId(sectionId);
        return beSectionParameterMapper.selectByPrimaryKey(key);
    }

    private void addPrintNum(String sectionId) {
        BeSectionParameter param = getPrintParam(sectionId);
        Date now = new Date();
        if(param == null) {
            param = new BeSectionParameter();
            param.setSectionId(sectionId);
            param.setParamId(PARAM_HIDDEN_PRINTED);
            param.setParamValue(Constants.STR_YES);
            param.setMemo("暗标关联表已打印");
            param.setCreateTime(now);
            param.setUpdateTime(now);
            beSectionParameterMapper.insert(param);
        } else {
            Integer printedNum = OConvertUtils.getInt(param.getParamValue()) + 1;
            param.setParamValue(printedNum.toString());
            param.setUpdateTime(now);
            beSectionParameterMapper.updateByPrimaryKeySelective(param);
        }
    }


    @Value("${authLoginUrl}")
    private String authLoginUrl;
    @Autowired(required = false)
    private BeSectionParameterMapper beSectionParameterMapper;
    @Autowired
    private BeSectionReportService beSectionReportService;
}
